using System;
using System.Reflection;
using Microsoft.Xna.Framework;

namespace SolarWinds.Animations
{
    public abstract class Animation
    {
        #region Public Properties
		 
        private TimeSpan mBeginTime = TimeSpan.FromSeconds(0.0);

        public TimeSpan BeginTime
        {
            get { return mBeginTime; }
            set { mBeginTime = value; }
        }

        private TimeSpan mEndTime = TimeSpan.FromSeconds(1.0);

        public TimeSpan EndTime
        {
            get { return mEndTime; }
            set { mEndTime = value; }
        } 

        public TimeSpan Duration
        {
            get { return mEndTime - mBeginTime; }
            set { mEndTime = mBeginTime + value; }
        }

        private bool mEnabled;

        public bool Enabled
        {
            get { return mEnabled; }
            set { mEnabled = value; }
        }

        private Object mObject;

        public Object ControlledObject
        {
            get { return mObject; }
            set { mObject = value; }
        }

        /// <summary>
        /// The property that the animation controls
        /// </summary>
        private string mPropertyName;

        public string PropertyName
        {
            get { return mPropertyName; }
            set { mPropertyName = value; }
        }

        /// <summary>
        /// The channel of the property that the animation controls
        /// </summary>
        private string mChannelName;

        public string ChannelName
        {
            get { return mChannelName; }
            set { mChannelName = value; }
        }
        
        #endregion

        public Animation(Object controlled, string propertyName)
        {
            mObject = controlled;
            mPropertyName = propertyName;
            mChannelName = "";
        }

        public Animation(Object controlled, string propertyName, string channelName)
        {
            mObject = controlled;
            mPropertyName = propertyName;
            mChannelName = channelName;
        }

        protected void SetChannel(float value)
        {
            PropertyInfo pi = ControlledObject.GetType().GetProperty(PropertyName);
            object property = pi.GetValue(ControlledObject, null);

            PropertyInfo ci = pi.PropertyType.GetProperty(ChannelName);
            if (ci == null)
            {
                FieldInfo fi = pi.PropertyType.GetField(ChannelName);
                if (fi == null)
                {
                    pi.SetValue(ControlledObject, 
                                Convert.ChangeType(value, pi.PropertyType), null);
                }
                else
                {
                    fi.SetValue(property, 
                                Convert.ChangeType(value, fi.FieldType));

                    pi.SetValue(ControlledObject, property, null);
                }
            }
            else
            {
                ci.SetValue(property, 
                            Convert.ChangeType(value, ci.PropertyType), null);

                pi.SetValue(ControlledObject, property, null);
            }

        }

        public abstract void Update(GameTime gameTime);
    }
}